﻿/*
** Haaf's Game Engine 1.5
** Copyright (C) 2003-2004, Relish Games
** hge.relishgames.com
**
** hgeGUI helper classes header
*/
module core.hgegui_bak;
 
private	import		core.hgeall;



const HGEGUI_NONAVKEYS		=0;
const HGEGUI_LEFTRIGHT		=1;
const HGEGUI_UPDOWN		=2;
const HGEGUI_CYCLED		=4;

const	VK_LBUTTON=1;//鼠标左键
const	VK_RBUTTON=2;//鼠标右键
const	VK_CANCEL=3;//Ctrl+Break(通常不需要处理)
const	VK_MBUTTON=4;//鼠标中键


/*
** hgeGUIObject
*/
class hgeGUIObject
{
public:
	this()	{	if(!hge)hge = gameInfo.hge(); }

	 void	Render() {};
	 void	Update(float dt) {}

	 void	Enter() {}
	 void	Leave() {}
	 bool	IsDone() { return true; }
	 void	Focus(bool bFocused) {}
	 void	MouseOver(bool bOver) {}

	 bool	MouseMove(float x, float y) { return false; }
	 bool	MouseLButton(bool bDown) { return false; }
	 bool	MouseRButton(bool bDown) { return false; }
	 bool	MouseWheel(int nNotches) { return false; }
	 bool	KeyClick(int key, int chr) { return false; }

	int				id;
	bool			bStatic;
	bool			bVisible;
	bool			bEnabled;
	char[]			gtxt;	//控件名称 
	hgeRect			rect;

	hgeGUI			gui;
	hgeGUIObject	next;
	hgeGUIObject	prev;

protected:
	this( hgeGUIObject go){
		this.id= go.id;
		this.bStatic= go.bStatic;
		this.bVisible= go.bVisible;
		this.bEnabled= go.bEnabled;
		this.rect	= go.rect;
		this.gui	= go.gui;
		this.next	= go.next;
		this.prev	= go.prev;
	}
	hgeGUIObject  opCatAssign(hgeGUIObject  go){
				this.id= go.id;
		this.bStatic= go.bStatic;
		this.bVisible= go.bVisible;
		this.bEnabled= go.bEnabled;
		this.rect	= go.rect;
		this.gui	= go.gui;
		this.next	= go.next;
		this.prev	= go.prev;

		return go;
	}
	static ifHge 	hge;
};


/*
** hgeGUI
*/
class hgeGUI
{
public:
	this()
	{
		if(!hge)hge = gameInfo.hge();

		ctrls=null;
		ctrlLock=null;
		ctrlFocus=null;
		ctrlOver=null;
		navmode=HGEGUI_NONAVKEYS;
		bLPressed=bLLastPressed=false;
		bRPressed=bRLastPressed=false;
		nWheel=0;
		mx=my=0.0f;
		nEnterLeave=0;
		sprCursor=null;
	}

	
	~this()
	{
		hgeGUIObject 	ctrl=ctrls;
		hgeGUIObject 	nextctrl;
		mes(" 	GUI-> 开始销毁控件 ------");
		while(ctrl)
		{
			nextctrl=ctrl.next;
			mes(" 		GUI -> 销毁控件		"~ctrl.gtxt);
			delete ctrl;	
			ctrl=nextctrl;
		}

	}
	

	void	AddCtrl(hgeGUIObject ctrl)
		{
			static int i;
			i++;
			hgeGUIObject last=ctrls;

			ctrl.gui=this;

			if(!ctrls)
			{
				ctrls=ctrl;
				ctrl.prev=null;
				ctrl.next=null;
			}
			else
			{
				while(last.next) last=last.next;
				last.next=ctrl;
				ctrl.prev=last;
				ctrl.next=null;
			}
			mes(" 		GUI -> 加入控件		"~ctrl.gtxt~", 		index==",i);
		}


	void	DelCtrl(int id)
		{
			hgeGUIObject ctrl=ctrls;

			while(ctrl)
			{
				if(ctrl.id == id)
				{
					if(ctrl.prev) ctrl.prev.next = ctrl.next;
					else ctrls = ctrl.next;
					if(ctrl.next) ctrl.next.prev = ctrl.prev;
					delete ctrl;
					return;
				}
				ctrl=ctrl.next;
			}
		}
	
	hgeGUIObject	GetCtrl(int id)
				{
					hgeGUIObject ctrl=ctrls;

					while(ctrl)
					{
						if(ctrl.id == id) return ctrl;
						ctrl=ctrl.next;
					}

					return null;
				}

	
	void MoveCtrl(int id, float x, float y)
			{
				hgeGUIObject ctrl=GetCtrl(id);
				ctrl.rect.x2=x + (ctrl.rect.x2 - ctrl.rect.x1);
				ctrl.rect.y2=y + (ctrl.rect.y2 - ctrl.rect.y1);
				ctrl.rect.x1=x;
				ctrl.rect.y1=y;
			}

	
	void	ShowCtrl(int id, bool bVisible)
		{
			GetCtrl(id).bVisible=bVisible;
		}

	
	void	EnableCtrl(int id, bool bEnabled)
		{
			GetCtrl(id).bEnabled=bEnabled;
		}

	void	SetNavMode(int mode)
			{
				navmode=mode;
			}
	void	SetCursor(hgeSprite spr)
			{
				sprCursor=spr;
			}
	void	SetFocus(int id)
			{
				hgeGUIObject ctrlNewFocus=GetCtrl(id);

				if(ctrlNewFocus==ctrlFocus) return;
				if(!ctrlNewFocus)
				{
					if(ctrlFocus) ctrlFocus.Focus(false);
					ctrlFocus=null;
				}
				else if(!ctrlNewFocus.bStatic && ctrlNewFocus.bVisible && ctrlNewFocus.bEnabled)
				{
					if(ctrlFocus) ctrlFocus.Focus(false);
					if(ctrlNewFocus) ctrlNewFocus.Focus(true);
					ctrlFocus=ctrlNewFocus;
				}
			}
	int	 GetFocus()  
		{
			if(ctrlFocus) return ctrlFocus.id;
			else return 0;
		}
	
	void Enter()
		{
			hgeGUIObject ctrl=ctrls;

			while(ctrl)
			{
				ctrl.Enter();
				ctrl=ctrl.next;
			}
			nEnterLeave=2;
		}
	void Leave()
		{
			hgeGUIObject ctrl=ctrls;

			while(ctrl)
			{
					ctrl.Leave();
					ctrl=ctrl.next;
			}

			ctrlFocus=null;
			ctrlOver=null;
			ctrlLock=null;
			nEnterLeave=1;
		}

	int		Update(float dt)
			{
				bool bDone;
				int key;
				hgeGUIObject ctrl;

			// Update the mouse variables

				hge.Input_GetMousePos(&mx, &my);
				bLLastPressed=bLPressed;
				bLPressed=hge.Input_GetKeyState(VK_LBUTTON);
				bRLastPressed=bRPressed;
				bRPressed=hge.Input_GetKeyState(VK_RBUTTON);
				nWheel=hge.Input_GetMouseWheel();

			// Update all controls

				ctrl=ctrls;
				while(ctrl)
				{
					ctrl.Update(dt);
					ctrl=ctrl.next;
				}

			// Handle Enter/Leave

				if(nEnterLeave)
				{
					ctrl=ctrls; bDone=true;
					while(ctrl)
					{
						if(!ctrl.IsDone()) { bDone=false; break; }
						ctrl=ctrl.next;
					}
					if(!bDone) return 0;
					else
					{
						if(nEnterLeave==1) return -1;
						else nEnterLeave=0;
					}
				}

			// Handle keys	

				key=hge.Input_GetKey();
				if(((navmode & HGEGUI_LEFTRIGHT) && key==HGEK_LEFT) ||
					((navmode & HGEGUI_UPDOWN) && key==HGEK_UP))
				{
					ctrl=ctrlFocus;
					if(!ctrl)
					{
						ctrl=ctrls;
						if(!ctrl) return 0;
					}
					do {
						ctrl=ctrl.prev;
						if(!ctrl && ((navmode & HGEGUI_CYCLED) || !ctrlFocus))
						{
							ctrl=ctrls;
							while(ctrl.next) ctrl=ctrl.next;
						}
						if(!ctrl || ctrl==ctrlFocus) break;
					} while(ctrl.bStatic==true || ctrl.bVisible==false || ctrl.bEnabled==false);

					if(ctrl && ctrl!=ctrlFocus)
					{
						if(ctrlFocus) ctrlFocus.Focus(false);
						if(ctrl) ctrl.Focus(true);
						ctrlFocus=ctrl;
					}
				}
				else if(((navmode & HGEGUI_LEFTRIGHT) && key==HGEK_RIGHT) ||
					((navmode & HGEGUI_UPDOWN) && key==HGEK_DOWN))
				{
					ctrl=ctrlFocus;
					if(!ctrl)
					{
						ctrl=ctrls;
						if(!ctrl) return 0;
						while(ctrl.next) ctrl=ctrl.next;
					}
					do {
						ctrl=ctrl.next;
						if(!ctrl && ((navmode & HGEGUI_CYCLED) || !ctrlFocus)) ctrl=ctrls;
						if(!ctrl || ctrl==ctrlFocus) break;
					} while(ctrl.bStatic==true || ctrl.bVisible==false || ctrl.bEnabled==false);

					if(ctrl && ctrl!=ctrlFocus)
					{
						if(ctrlFocus) ctrlFocus.Focus(false);
						if(ctrl) ctrl.Focus(true);
						ctrlFocus=ctrl;
					}
				}
				else if(ctrlFocus && key && key!=HGEK_LBUTTON && key!=HGEK_RBUTTON)
				{
					if(ctrlFocus.KeyClick(key, hge.Input_GetChar())) return ctrlFocus.id;
				}

			// Handle mouse

				if(ctrlLock)
				{
					ctrl=ctrlLock;
					if(!bLPressed && !bRPressed) ctrlLock=null;
					if(ProcessCtrl(ctrl)) return ctrl.id;
				}
				else
				{
					// Find last (topmost) control

					ctrl=ctrls;
					if(ctrl)
						while(ctrl.next) ctrl=ctrl.next;		// 先找到最后点

					while(ctrl)		// 向前遍历
					{
						if(ctrl.rect.TestPoint(mx,my) && ctrl.bEnabled)
						{
							if(ctrlOver !is ctrl)
							{
								if(ctrlOver) ctrlOver.MouseOver(false);
								ctrl.MouseOver(true);
								ctrlOver=ctrl;
							}
							
							if(ProcessCtrl(ctrl)) return ctrl.id;
							else return 0;
							
							
						}
						ctrl=ctrl.prev;
					}

					if(ctrlOver) {ctrlOver.MouseOver(false); ctrlOver=null;}

				}

				return 0;
			}
	
	void	Render()
			{
			
				hgeGUIObject ctrl=ctrls;
	
				while(ctrl)
				{
					hgeFontCN.vmes(" render ctrl= "~ctrl.gtxt);
					if(ctrl.bVisible) ctrl.Render();
					ctrl=ctrl.next;
					
				}

				if(hge.Input_IsMouseOver() && sprCursor) sprCursor.Render(mx,my);
			}

private:
	this( hgeGUI gu){
		
		this.ctrls=		gu.ctrls;
		this.ctrlLock=	gu.ctrlLock;
		this.ctrlFocus=	gu.ctrlFocus;
		this.ctrlOver=	gu.ctrlOver;
		this.navmode=	gu.navmode;
		this.bLPressed= gu.bLPressed;
		this.bLLastPressed= gu.bLLastPressed;
		this.bRPressed=	gu.bRPressed;
		this.bRLastPressed=	gu.bRLastPressed;
		this.nWheel=gu.nWheel;
		this.mx=gu.mx;
		this.my=gu.my;
		this.nEnterLeave=gu.nEnterLeave;
		this.sprCursor=gu.sprCursor;
		};
		
	//hgeGUI&			operator= (const hgeGUI&);
	hgeGUI	opCatAssign(hgeGUI gu){//  用~= 连赋值 代替  = 操作符 
				this.ctrls=		gu.ctrls;
				this.ctrlLock=	gu.ctrlLock;
				this.ctrlFocus=	gu.ctrlFocus;
				this.ctrlOver=	gu.ctrlOver;
				this.navmode=	gu.navmode;
				this.bLPressed= gu.bLPressed;
				this.bLLastPressed= gu.bLLastPressed;
				this.bRPressed=	gu.bRPressed;
				this.bRLastPressed=	gu.bRLastPressed;
				this.nWheel=gu.nWheel;
				this.mx=gu.mx;
				this.my=gu.my;
				this.nEnterLeave=gu.nEnterLeave;
				this.sprCursor=gu.sprCursor;		
			return gu;
			}		
	
	bool	ProcessCtrl(hgeGUIObject ctrl)
			{
				bool bResult=false;

				if(!bLLastPressed && bLPressed)	{ ctrlLock=ctrl;SetFocus(ctrl.id);bResult=bResult || ctrl.MouseLButton(true); }
				if(!bRLastPressed && bRPressed)	{ ctrlLock=ctrl;SetFocus(ctrl.id);bResult=bResult || ctrl.MouseRButton(true); }
				if(bLLastPressed && !bLPressed)	{ bResult=bResult || ctrl.MouseLButton(false); }
				if(bRLastPressed && !bRPressed)	{ bResult=bResult || ctrl.MouseRButton(false); }
				if(nWheel) bResult=bResult || ctrl.MouseWheel(nWheel);
				bResult=bResult || ctrl.MouseMove(mx-ctrl.rect.x1,my-ctrl.rect.y1);

				return bResult;
			}

	static ifHge 	hge;

	hgeGUIObject	ctrls;
	hgeGUIObject	ctrlLock;
	hgeGUIObject	ctrlFocus;
	hgeGUIObject	ctrlOver;

	int				navmode;
	int				nEnterLeave;
	hgeSprite		sprCursor;

	float			mx,my;
	int				nWheel;
	bool			bLPressed, bLLastPressed;
	bool			bRPressed, bRLastPressed;
};

